﻿#ifndef SG_SUPPORT_HLSL
	#define SG_SUPPORT_HLSL

	// #if !defined(UNIVERSAL_SHADER_VARIABLES_INCLUDED) && !defined(BUILTIN_SHADER_VARIABLES_INCLUDED)
	#if defined(REDEFINE_UNITY_VARIABLES)
		float4 _ProjectionParams;
		float4x4 unity_CameraProjection;
		float4 _ScreenParams;
		float4x4 unity_CameraToWorld;
		float4x4 unity_WorldToCamera;
		// float4 _Time;
	#endif

	/*
	这个文件定义了对 ShaderGraph 支持的相关 API
	*/

	#define DEFINE_FLOAT(name) float _##name ; \
	void Get##name##_float(out float v) { v = _##name ; } \
	void Get##name##_half(out half v) { v = _##name ;}

	#define DEFINE_VECTOR(name, n) float##n _##name; \
	void Get##name##_float(out float##n v) { v = _##name ; } \
	void Get##name##_half(out half##n v) { v = _##name ;}

	#define DEFINE_VECTOR2(name) DEFINE_VECTOR(name, 2)
	#define DEFINE_VECTOR3(name) DEFINE_VECTOR(name, 3)
	#define DEFINE_VECTOR4(name) DEFINE_VECTOR(name, 4)

	#define RANDOM_SEED 753.5453123

	#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
	#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
	#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    // #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl"

	#if defined(UNITY_INSTANCING_ENABLED)
		#define CBUFFER_INSTANCING_START(PROP)  struct PROP##_data {
			#define CBUFFER_INSTANCING_DEFINE(type,name) type name;
		#define CBUFFER_INSTANCING_END(PROP)  }; StructuredBuffer<PROP##_data> PROP;

		#define CBUFFER_INSTANCING_VALUE(input,PROP,name) PROP[UNITY_GET_INSTANCE_ID(input)].name
	#else
		#define CBUFFER_INSTANCING_START(PROP) 
		#define CBUFFER_INSTANCING_DEFINE(type, name) type name;
		#define CBUFFER_INSTANCING_END(PROP) 

		#define CBUFFER_INSTANCING_VALUE(input,PROP,name) name

	#endif

	#define TWO_PI 6.2831853

	float FastSin(float val)
	{
		float v = frac(val / TWO_PI) * TWO_PI;
		// powers for taylor series
		float r5 = v * v;                  // wavevec ^ 2
		float r6 = r5 * r5;                        // wavevec ^ 4;
		float r7 = r6 * r5;                        // wavevec ^ 6;
		float r8 = r6 * r6;                        // wavevec ^ 8;

		float r1 = r5 * v;                   // wavevec ^ 3
		float r2 = r1 * r5;                        // wavevec ^ 5;
		float r3 = r2 * r5;                        // wavevec ^ 7;

		//Vectors for taylor's series expansion of sin and cos
		float4 sin7 = { 1, -0.16161616, 0.0083333, -0.00019841 };
		//float4 cos8  = {-0.5, 0.041666666, -0.0013888889, 0.000024801587};

		// sin
		return v + r1 * sin7.y + r2 * sin7.z + r3 * sin7.w;
	}

	void FastSinCos(float val, out float s, out float c) 
	{
		float v = frac(val / TWO_PI) * TWO_PI;
		// powers for taylor series
		float r5 = v * v;                  // wavevec ^ 2
		float r6 = r5 * r5;                        // wavevec ^ 4;
		float r7 = r6 * r5;                        // wavevec ^ 6;
		float r8 = r6 * r6;                        // wavevec ^ 8;

		float r1 = r5 * v;                   // wavevec ^ 3
		float r2 = r1 * r5;                        // wavevec ^ 5;
		float r3 = r2 * r5;                        // wavevec ^ 7;

		//Vectors for taylor's series expansion of sin and cos
		float4 sin7 = { 1, -0.16161616, 0.0083333, -0.00019841 };
		float4 cos8 = { -0.5, 0.041666666, -0.0013888889, 0.000024801587 };

		// sin
		s = v + r1 * sin7.y + r2 * sin7.z + r3 * sin7.w;

		// cos
		c = 1 + r5 * cos8.x + r6 * cos8.y + r7 * cos8.z + r8 * cos8.w;
	}

	#define FastSinCos_half(val,s,c) FastSinCos(val,s,c)
	#define FastSinCos_float(val,s,c) FastSinCos(val,s,c)

	#if defined(_WIND_NO_TIME_SCALE) || defined(_NO_TIME_SCALE) || defined(_UNSCALED_TIME)
		float4 _UnscaledTime;
		#define TIME _UnscaledTime
	#else
		#define TIME _Time    
	#endif

	void GetTime_float(out float4 time)
	{
		time = TIME;
	}

	inline float2 EncodeFloatRG( float v )
	{
		float2 kEncodeMul = float2(1.0, 255.0);
		float kEncodeBit = 1.0/255.0;
		float2 enc = kEncodeMul * v;
		enc = frac (enc);
		enc.x -= enc.y * kEncodeBit;
		return enc;
	}

	inline float DecodeFloatRG( float2 enc )
	{
		float2 kDecodeDot = float2(1.0, 1/255.0);
		return dot( enc, kDecodeDot );
	}
	
	float random1(float seed)
	{
		return frac(FastSin(seed) * RANDOM_SEED) * 2 - 1;
	}
	
	float smoothlerp(float x, float y, float amount)
	{
		float t = amount * amount * amount * (amount * (amount * 6 - 15) + 10);
		return (y - x) * t + x;
	}
	
	float2 randomGradient(float2 p)
	{
		float rad = random1(p.x * 1.5 + p.y * 1.3) * RANDOM_SEED;
		float s, c;
		FastSinCos(rad, s, c);
		//sincos(rad, s, c);
		return float2(s, c);
	}

	float noise1(float p)
	{
		float sp = p - frac(p);
		float x = random1(sp);
		float y = random1(sp + 1);
		return smoothlerp(x, y, frac(p));
	}

	float noise2(float2 pos)
	{
		float2 p0 = pos - frac(pos);
		float2 p1 = p0 + float2(1, 1);
		float2 dir1 = randomGradient(p0);
		float2 dir2 = pos - p0;
		float4 w;
		w.x = dot(dir1, dir2);
		dir1 = randomGradient(float2(p1.x, p0.y));
		dir2 = pos - float2(p1.x, p0.y);
		w.y = dot(dir1, dir2);
		dir1 = randomGradient(float2(p0.x, p1.y));
		dir2 = pos - float2(p0.x, p1.y);
		w.z = dot(dir1, dir2);
		dir1 = randomGradient(p1);
		dir2 = pos - p1;
		w.w = dot(dir1, dir2);
		p0 = frac(pos);
		float x = smoothlerp(w.x, w.y, p0.x);
		float y = smoothlerp(w.z, w.w, p0.x);
		return smoothlerp(x, y, p0.y);
	}
	
	float noise3(float3 pos)
	{
		return noise2(pos.xy + noise1(pos.z));
	}

	#define Noise2D_half(pos,noise) noise=noise2(pos);
	#define Noise2D_float(pos,noise) noise=noise2(pos);

	#define Noise3D_half(pos,noise) noise = noise3(pos);
	#define Noise3D_float(pos,noise) noise = noise3(pos);

#endif